#pragma once
#include <cstdio>
#include <ctime>
#include <iostream>
#include <string>
#include <memory>
#include <random>
#include <sstream>
#include <atomic>
#include <iomanip>
#include <jsoncpp/json/json.h>

namespace rpc
{
    #define DEBUG 0
    #define LINT 1
    #define ERROR 2

    #define LDEFAULT DEBUG
    #define LOG(lever, format, ...) {\
        if(lever >= LDEFAULT)\
        {\
            time_t t = time(nullptr);\
            struct tm* lt = localtime(&t);\
            char time_tmp[32] = {0};\
            strftime(time_tmp, 31, "%m-%d %T", lt);\
            printf("[%s][%s:%d] " format "\n", time_tmp, __FILE__, __LINE__, ##__VA_ARGS__);\
        }\
    }

    #define DLOG(format, ...) LOG(DEBUG, format, ##__VA_ARGS__);
    #define LLOG(format, ...) LOG(LINT, format, ##__VA_ARGS__);
    #define ELOG(format, ...) LOG(ERROR, format, ##__VA_ARGS__);

    // 序列化和反序列化
    class JSON
    {
    public:
        static bool serialize(const Json::Value& str, std::string& body)
        {
            // 输出对象
            std::stringstream ss;
            // 建立工厂对象
            Json::StreamWriterBuilder val;
            // 实例化出派生对象
            std::unique_ptr<Json::StreamWriter> value(val.newStreamWriter());
            // 序列化
            int ret = value->write(str, &ss);
            if(ret != 0)
            {
                ELOG("serialize error");
                return false;
            }
            body = ss.str();
            return true;
        }
        static bool unserialize(const std::string &body, Json::Value &val)
        {
            // 实例化出工厂
            Json::CharReaderBuilder crb;
            std::string errs;
            //通过工厂类对象来生产派生类对象
            std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
            // 反序列化
            bool ret = cr->parse(body.c_str(), body.c_str() + body.size(), &val, &errs);
            if(ret == false)
            {
                ELOG("unserialize error");
                return false;
            }
            return true;
        }
    };
    // 生成UUID
    class UUID
    {
    public:
        static std::string Uuid()
        {
            // 返回对象
            std::stringstream ss;
            // 构造机器随机对象
            std::random_device rd;
            // 根据机器随机对象构造伪随机对象
            std::mt19937 generator(rd());
            // 构造限定数据范围
            std::uniform_int_distribution<int> distribution(0, 255);
            // std::cout << distribution(generator) << std::endl;
            // 生成随机数
            for(int i = 0; i < 8; i++)
            {
                if(i == 4 || i == 6)
                    ss << "-";
                // 以十六进制生成
                ss << std::setw(2) << std::setfill('0') << std::hex << distribution(generator);
            }
            ss << '-';
            static std::atomic<size_t> seq(1);
            size_t cur = seq.fetch_add(1);
            for (int i = 7; i >= 0; i--) 
            {
                if (i == 5) ss << "-";
                // 以十六进制生成数字
                ss << std::setw(2) << std::setfill('0') << std::hex << ((cur >> (i*8)) & 0xFF);
            }
            return ss.str();
        }
    };
}